计算机基础知识

undefined

  • 计算机基础

undefined操作系统的发展历史

计算机基础知识 - 图1

图片来自:

http://www.catb.org/esr/writings/taoup/html/ch03s02.html

Design of the UNIX Operating System (1986) by Maurice Bach

不但是最好的操作系统教育的书, 也是极少数解释Terminal 驱动器的。

undefined程序类型

按照界面交互形式可以分为2类

界面类型擅长的系统
textual interfaceLinux, UNIX
pictorialinterfaceMac, Windows

计算机上的程序可以按照运行模式分为3类:

程序类型说明实例程序名称
batch:不跟人接触,自己执行完结束。ls, cp, mv, mkdir
interactive :跟用户接触nano, password, mksh
daemon :不跟用户直接接触, 永久运行nginx, bitcoind

undefined字节

计算机执行程序时,组成程序的指令和程序所操作的数据需要存储在某个地方,这个

地方即为计算机的内存。可以直接操作的内存的最小单位是字节(byte),一个字节由8

个位(bit)组成,每个字节都有唯一的地址。如果存储无符号整数,一个字节可以表示0-

255范围内的数字。

计算机基础知识 - 图2

计算机基础知识 - 图3

计算机基础知识 - 图4

计算机基础知识 - 图5

计算机基础知识 - 图6

undefined字节的大小端

计算机基础知识 - 图7

undefined地址

计算机基础知识 - 图8

计算机基础知识 - 图9

计算机基础知识 - 图10

undefined图灵完备

图灵完备是什么意思呢?

在可计算理论中,当一组数据操作的规则(一组指令集,编程语言,或者元胞自动机)满足任意数据按照一定的顺序可以计算出结果,被称为图灵完备(turing complete)。一个有图灵完备指令集的设备被定义为通用计算机。如果是图灵完备的,它(计算机设备)有能力执行条件跳转(“if” 和 “goto”语句)以及改变内存数据。 如果某个东西展现出了图灵完备,它就有能力表现出可以模拟原始计算机,而即使最简单的计算机也能模拟出最复杂的计算机。所有的通用编程语言和现代计算机的指令集都是图灵完备的(C++ template就是图灵完备的),都能解决内存有限的问题。图灵完备的机器都被定义有无限内存,但是机器指令集却通常定义为只工作在特定的,有限数量的RAM上。

图灵不完备的语言常见原因有循环或递归受限(无法写不终止的程序,如 while(true){}; ), 无法实现类似数组或列表这样的数据结构(不能模拟纸带). 这会使能写的程序有限图灵完备可能带来坏处, 如C++的模板语言, 模板语言是在类型检查时执行, 如果编译器不加以检查,我们完全可以写出使得C++编译器陷入死循环的程序.图灵不完备也不是没有意义, 有些场景我们需要限制语言本身. 如限制循环和递归, 可以保证该语言能写的程序一定是终止的.

undefined操作系统中字节表示

32位系统中, 标准数字用4个字节表示. 整数的范围是2的32次方.

64位系统中, 定义证书int 也是4个字节. long int 时是8字节

字符串通过ASCII码来表示0-255范围内与字母等的对应.

中文字有其他的规则来对应. 例如utf8.

![image_1btoa8s9oog1chl4ct1c3t24e9.png-152.3kB][36]

undefinedWindows研发思想的来龙去脉

多进程的管理来自于UNIX

从系统的角度, 和从进程自己的角度来看内存.

程序自己的地址是连续的, 实际系统中不是连续的, 是多个程序公用内存段落.

  1. graph LR
  2. unix-->OpenVMS
  3. OpenVMS-->WindowsNT
  4. WindowsNT -->Windows2000
  5. Windows2000-->WindowsXP

UNIX —> BSD

—> SysV

—-> Linux

undefined执行程序对比

系统文件对比执行动态链接库静态链接库编译结果源文件
windows:.exe.dll.lib.obj.c
linux:无后缀.so.a.o.c
  • 编译器是把非执行文件转换成执行文件。
  • .exe:直接运行程序,
  • .dll:一套函数不能运行,但可以在另一个程序运行的,更高级也可一共享,程序运行中可以引用的。
  • .lib:造一个程序可以运行,但必须重新编译才成实现,程序可以互相共享
  • .obj:链接以前的编译结果,一个程序有若干个源程序,一个源程序一个Obj文件。半成品文件编译还未处理
  • .a 是若干个 .o 组成的,.a 到 .so 需要加若干个源数据。.so是 .a加工后的。

undefinedBASE64

Base64说明:

[https://baike.baidu.com/item/base64/8545775?fr=aladdin][37]

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。

undefined执行速度

  • register read = 1 nanosecond 纳秒
  • memory read = 1 microsecond 微秒
  • file read = 1 millisecond 毫秒

undefinedTCP 接收 HTTP

以 GET, POST, PUT, DELETE, HEAD 开头.

undefined内存中栈与堆的区别

堆和栈的第一个区别就是申请方式不同:栈(英文名称是stack)是系统自动分配空间的,例如我们定义一个 char a;系统会自动在栈上为其开辟空间。

而堆(英文名称是heap)则是程序员根据需要自己申请的空间,例如malloc(10);开辟十个字节的空间。

由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。

而堆上的数据只要程序员不释放空间,就一直可以访问到,不过缺点是一旦忘记释放会造成内存泄露。

从下面代码可以看出:

  1. int a = 0; //全局初始化区
  2. char *p1; //全局未初始化区
  3. main()
  4. {
  5. int b; //栈
  6. char s[] = "abc"; //栈
  7. char *p2; //栈
  8. char *p3 = "123456"; //123456\0在常量区,p3在栈上。
  9. static int c =0 //全局(静态)初始化区
  10. p1 = (char *)malloc(10); //堆
  11. p2 = (char *)malloc(20); //堆

![image_1bu134etlerc8641f4g1dagglep.png-74.9kB][38]

undefined状态机

..

undefined形式语言

..

undefinedstack based machine

Compilers for stack machines are simpler and quicker to build than compilers for other machines. Code generation is trivial and independent of prior or subsequent code. For example, given an expression x+y*z+u, the corresponding syntax tree would be:

![image_1bv3kbvvj4uf12u31ata1avc1n8f1g.png-33.9kB][39]

The compiled code for a simple stack machine would take the form:

  1. push x
  2. push y
  3. push z
  4. multiply
  5. add
  6. push u
  7. add

undefined逆波兰表达式

Reverse Polish Notation

逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。

可以将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)(c+d)转换为ab+cd+

它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下:

如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。

在数据结构和编译原理这两门课程中都有介绍,下面是一些例子:

4 * ( A + B) 的堆栈变化过程示意:

![image_1bv3bj49g17661el1ql71heauap9.png-10.1kB][40]

(6*(4+5) - 25 )/(2+3) 的例子的二叉树表示:

![image_1bv3cqt0g1n611dr21l6ms6k1t0j1g.png-59.3kB][41]

34+56 = 42 的整个计算过程图示:

![image_1bv3bpor7s2rlma19dl1id5dn913.png-382.2kB][42]

12 * ( 3 + 4 ) - 6 + ( 8 / 2 ) = 82 的运算过程图示:

![image_1bv3d1c4s1aij1s71uvn437m2t9.png-17.2kB][43]

正常的表达式 —-> 逆波兰表达式

a+b —-> a,b,+

a+(b-c) —-> a,b,c,-,+

a+(b-c)d —-> a,b,c,-,d,,+

a+d(b-c)—->a,d,b,c,-,,+

a=1+3 —-> a=1,3 +

http=(smtp+http+telnet)/1024 写成什么呢?

http,smtp,http,+,telnet,+,1024,/,=

undefinedPostfix evaluation algorithm

  • Here is an algorithm for evaluating postfix expressions using a [[Stack (abstract data type)|stack]] (under this algorithm the expression is processed from ''left to right''):
  1. for each token in the postfix expression:
  2. if token is an operator:
  3. operand_2 pop from the stack
  4. operand_1 pop from the stack
  5. result evaluate token with operand_1 and operand_2
  6. push result back onto the stack
  7. else if token is an operand:
  8. push token onto the stack
  9. result pop from the stack